#include "./ntc_sensor.h"
#include "../device/gpio.h"
#include "./i2c.h"
#include "../rtx/rtx_os.h"
#include "./trmap.h"

namespace driver {

using namespace device::gpio;
using namespace utils;

using SDA = PB<7>;
using SCL = PB<8>;
using RDY = PB<6>;

static constexpr uint8_t ADDR = 0x48;

using ADS1115 = I2cInterface<ADDR, SCL, SDA>;

static constexpr uint8_t CONVERSION_REG = 0;
static constexpr uint8_t CONFIG_REG = 1;

static constexpr uint16_t CH1_CFG = 0x8483;
static constexpr uint16_t CH2_CFG = 0xB483;

const uint32_t TR_COUNT = sizeof (TRMap) / sizeof (TRMap[0]);
const uint32_t R_MIN = TRMap[TR_COUNT - 1];
const uint32_t R_MAX = TRMap[0];
constexpr uint32_t NOT_FOUND_INDEX = static_cast<uint32_t>(-1);

NtcSensor::NtcSensor() {

    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

    config_od_out<SCL, SDA>();
    config_float_input<RDY>();
    ADS1115::stop();
}

static uint32_t find(uint32_t val) {
    if ((val > R_MAX) || (val < R_MIN)) {
        return NOT_FOUND_INDEX;
    }
    uint32_t left = 0;
    uint32_t right = TR_COUNT - 1;

    while ((right - left) > 1) {
        uint32_t index = (left + right) / 2;
        uint32_t cv = TRMap[index];
        if (val > cv) {
            right = index;
        } else if (val < cv) {
            left = index;
        } else {
            return index;
        }
    }
    return left;
}

static bool read(uint16_t cfg, uint32_t &val) {
    uint16_t v;
    bool r = ADS1115::write(CONFIG_REG, cfg);
    if (!r) {
        return false;
    }

    r = ADS1115::read(CONVERSION_REG, v);
    if (!r) {
        return false;
    }

    uint32_t tmp = v * 2048 / 32768;
    val = 20000 * tmp / (1800 - tmp);

    return true;
}

bool read_find(uint16_t cfg, int16_t &val) {
    uint32_t tmp;
    bool ret = read(cfg, tmp);
    if (!ret) {
        return false;
    }
    uint32_t index = find(tmp);
    if (index == NOT_FOUND_INDEX) {
        return false;
    }
    val = static_cast<int16_t>(index) - 40;

    return true;
}

void NtcSensor::read_all() {
    m_water_ok = read_find(CH1_CFG, m_water_temp);
    
    m_steam_ok = read_find(CH2_CFG, m_steam_temp);
}


}








